﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI.WebControls;
using Grishko.DataTier;
using Grishko.SerilizeTools;
using Grishko.Tools;
using OutdoorLib.BaseEntity.Agency;
using OutdoorLib.BaseEntity.Dictionary;
using OutdoorLib.BaseEntity.Face;
using OutdoorLib.BaseEntity.Infrastructure;
using OutdoorLib.BaseEntity.Provider;
using OutdoorLib.BaseEntity.WS;
using OutdoorLib.Securety;
using OutdoorLib.WS;
using System.Web.UI;
using System.Text;

/// <summary>
/// Summary description for AppEnvirvoment
/// </summary>
public class AppEnvironment
{

    /// <summary>
    /// Карта типов 
    /// </summary>
    public class TypeMap 
    {
        
        public static List<TypeMapItem> GetSource()
        {
                        
            return CurrentProvider.Settings.TypeMapItems.ToList<TypeMapItem>();
            //return new List<TypeMapItem>();
        }

    }

    public class Helper
    {
        /// <summary>
        /// Возвращает коллекцию объектов соответв тэгу
        /// </summary>
        /// <param name="TagName"></param>
        /// <returns></returns>
        public static List<EntitySingle> GetObjectCollection(string TagName)
        {
            List<EntitySingle> result = new List<EntitySingle>();
            SecuretyContext SC = AppContext.GetSC();
            try
            {

                string sql = string.Format ( "select ObjectXML  from vSrchStorageLinks  where TagName='{0}'",TagName );

                if (string.IsNullOrEmpty(sql))
                    return result;

                System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
                cmd.CommandText = sql;
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.Connection = SC.Connection;
                SC.Connection.Open();

                DataSet DS = new DataSet();
                System.Data.SqlClient.SqlDataAdapter SqlD = new System.Data.SqlClient.SqlDataAdapter();
                SqlD.SelectCommand = cmd;
                SqlD.Fill(DS);
                if (0 == DS.Tables.Count)
                    return result;
                foreach (DataRow rw in DS.Tables[0].Rows)
                {                    
                    string s=rw[0].ToString();
                    EntitySingle obj = (EntitySingle)EntityActivator.CreateInstance(s);
                    obj.ReadXml(s);
                    
                    result.Add(obj);
                }

            }
            finally
            {
                SC.Connection.Close();
            }

            return result;

        }
        
        public static DataSet  GetDS(string SQL)
        {
            SecuretyContext SC = AppContext.GetSC();
            SqlTools tls = new SqlTools(SC);
            DataSet DS= tls.ExecuteSql(SQL);
            return DS;
        }

        public static EntitySingle GetObject(string ObjectID)
        {
            return SqlTools.GetEntitySingle(ObjectID);
        }

        public static void RegistredStartUpAlert(Control Page, List<string> source)
        {
            StringBuilder sb = new StringBuilder();
            foreach (string i in source )
            {
                sb.AppendFormat("{0} <br />" , i);
            }
            string script = "alert('" + sb.ToString() + "');";
            ScriptManager.RegisterStartupScript (Page,Page.GetType (),Guid .NewGuid ().ToString (),script ,true );
        }

        public static void HideAlertMessage(Control Page)
        {
            ScriptManager.RegisterStartupScript(Page, Page.GetType (), Guid.NewGuid().ToString(), "HideAlert();", true); 
        }
    }

    public class FilterSource
    {
        public static string GetNewRecordParam_Filter(string  ListTagName)
        {
            string s =  ListTagName;            
            return s;
        }



        public static Filter Save(Filter obj)
        {
            bool bIsNewRecord = OutdoorLib.Context.AgencyLib_GlobalConstants.IsNewRecord(obj.ID);
            AgencyEntity a = GlobalConstants.CurrentAgency;
            Employeer em = GlobalConstants.CurrentEmployeer;
            Employeer empl = a.GetEmployeer(em.ID);

            if (bIsNewRecord)
            {
                obj.ID = Guid.NewGuid().ToString();

                if (obj.ListCategory == Filter.ListEntityCategory.User)
                {
                    empl.FilterList.Add(obj);
                }
                else
                {

                    a.FilterList.Add(obj);
                }
            }

            if (obj.ListCategory == Filter.ListEntityCategory.User)
            {
                empl.FilterList.Remove(obj.ID);
                empl.FilterList.Add(obj);
                empl.Save();                
            }
            else
            {
                a.FilterList.Remove(obj.ID);
                a.FilterList.Add(obj);
                wsAgency.SaveAgency();
            }

            wsAgency.Reset();
            return obj;

        }

        public static Filter GetNewListWhere (string ID, string TagName)
        {
            if (CacheTools.IsSessionCacheObject(ID))
                return (Filter)CacheTools.GetSessionCacheObect(ID);


            Filter l = (Filter)EntityActivator.CreateInstance__(TagName);
            l.ID = GlobalConstants.GetID(ID);

            if (null == l.Where)
                    throw new Exception(string.Format("Не найден тип для метки {0}", TagName));

            CacheTools.SetSessionCacheObject(ID, l); 
            
            return l;

        }

        /// <summary>
        /// Врнуть фильтр 
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        public static Filter Get(string ID)
        {          

            Func<Filter> GetFilterValue = delegate
            {
                List<Filter> list = FullList;

                var res =
                from p in list
                where p.ID == ID
                select p;

                foreach (object f in res)
                {
                    return (Filter)f;
                }
                return null;
            };
          
            return GetFilterValue();
        }
        /// <summary>
        /// Выдать набор фильтров заданной категории и заданног tagname
        /// </summary>
        /// <param name="TagName"></param>
        /// <param name="Category"></param>
        /// <returns></returns>
        public static List<Filter> Get(string TagName , Filter.ListEntityCategory Category  )
        {

                List<Filter> result = new List<Filter>();
                List<Filter> list = FullList;

                var res =
                from p in list
                where p.TagName.ToUpper () == TagName.ToUpper () && p.ListCategory ==Category 
                orderby p.Caption 
                select p;

                foreach (object f in res)
                {
                    result .Add (( Filter)f);
                }
            
            

            return result ;
        }

        /// <summary>
        /// вернуть фильтры заданного типа
        /// </summary>
        /// <param name="ListType"></param>
        /// <returns></returns>
        public static List<Filter> GetFilters(string  ListType)
        {
            List<Filter> source = FullList;
            var result =
                from r in source
                where r.TagName == ListType
                select r;
            return result.ToList<Filter>();
        }

        public static void Delete(Filter obj) 
        {
            switch (obj.ListCategory)
            { 
                case Filter.ListEntityCategory.User   :
                    CurrentEmployeer.FilterList.Remove(obj.ID);                    
                    break;
                case Filter.ListEntityCategory .Client :
                    CurrentAgency.FilterList.Remove(obj.ID);
                    break;
            }
            wsAgency.SaveAgency();
        }

        /// <summary>
        /// полный список всех фильтров - провайдера/агентсв/текущего пользователя
        /// </summary>
        private static List<Filter> FullList
        {
            get
            {
                List<Filter> result = new List<Filter>();
                Func<EntityList, Filter.ListEntityCategory, bool> fAdd = delegate(EntityList l, Filter.ListEntityCategory Type)
                {
                    foreach (Filter f in l)
                    {
                        f.ListCategory = Type;
                        result.Add(f);
                    }
                    return true;
                };

                fAdd(AppEnvironment.CurrentProvider.FilterList, Filter.ListEntityCategory.Provider);
                fAdd(AppEnvironment.CurrentEmployeer.FilterList, Filter.ListEntityCategory.User);
                fAdd(AppEnvironment.CurrentAgency.FilterList, Filter.ListEntityCategory.Client);


                return result;

            }
        }



    }

    public class DictionarySource
    {
        /// <summary>
        /// Полный набор справочников
        /// </summary>
        /// <returns></returns>
        public static List<TreeDictionaryItem> GetTreeDictionaryList() { return wsDictionary.GetTreeDictionaryList(); }

        /// <summary>
        /// Набор справочников заданного типа 
        /// </summary>
        /// <returns></returns>
        public static TreeDictionaryItem[] GetTreeDictionaryList(string TypeID) { return wsDictionary.GetTreeDictionaryList(TypeID); }
                
        /// <summary>
        /// системные справочники
        /// </summary>
        /// <returns></returns>
        public static List<TreeDictionaryItem> GetProviderTreeDictionaryList() { return wsDictionary.GetProviderTreeDictionaryList(); }

        /// <summary>
        /// справочники агентсва
        /// </summary>
        /// <returns></returns>
        public static List<TreeDictionaryItem> GetAgencyTreeDictionaryList() { return wsDictionary.GetAgencyTreeDictionaryList(); }

        /// <summary>
        /// вернуть справочник по ключу.
        /// Возвращает первый справочник соотв. 
        /// </summary>
        /// <param name="Key"></param>
        /// <returns></returns>
        public static TreeDictionaryItem GetTreeDictionaryItem(string TypeID)
        {
            {
                TreeDictionaryItem w = wsDictionary.GetTreeDictionaryItem(TypeID);  
                 return w;
            }
        }

        public static Func<TreeDictionaryItem> GetTreeDictionaryItem_F_AdressProgramm()
        {
           TreeDictionaryItem[]  res =AppEnvironment.DictionarySource.GetTreeDictionaryList(TreeDictionaryItem.TreeDictionary_AdressProgram);
            var result =
                from i in res
                orderby i.Name           
                select i;

            //TreeDictionaryItem tree = new TreeDictionaryItem() { TypeID = TreeDictionaryItem.TreeDictionary_AdressProgram, ParamID = GlobalConstants.qProxyId, ID = GlobalConstants.qProxyId,Value = "Адресные программы" };
            TreeDictionaryItem tree = TreeDictionaryItem.GetProxyRoot(TreeDictionaryItem.TreeDictionary_AdressProgram, "Адресные программы");

            foreach (TreeDictionaryItem j  in result)
            {
                tree.ChildNodes.Add(j);
            }

            Func<TreeDictionaryItem> res_ = delegate()
            {
                return tree;
            };
            return res_;
            
    }

        /// <summary>
        /// вернуть справочник по ключу.
        /// Возвращает первый справочник соотв. 
        /// </summary>
        /// <param name="Key"></param>
        /// <returns></returns>
        public static Func<TreeDictionaryItem> GetTreeDictionaryItem_F(string TypeID)
        {
            {
                Func<TreeDictionaryItem> result = delegate()
                {
                    return GetTreeDictionaryItem(TypeID);
                };
                
                return result ;
            }
        }


        /// <summary>
        /// Создает новый справочник на основании инф. о типе 
        /// </summary>
        /// <param name="TypeID"></param>
        /// <returns></returns>
        public static TreeDictionaryItem CreateTreeDictionaryItem(string TypeID)
        {
            return wsDictionary.Create(TypeID);            
        }


        

        public static void Save(TreeDictionaryItem obj)
        {
            wsDictionary .SaveDictionary (obj);
        }



        public static TreeDictionaryItem GetTreeDictionaryItemWithTypeID(string TypeID)
        {
            { return wsDictionary.GetTreeDictionaryItemWithTypeID(TypeID); }
        }

        public static TreeDictionaryItem GetTreeDictionaryItemWithID(string ID)
        {
            { return wsDictionary.GetTreeDictionaryItemWithID(ID); }
        }

        /// <summary>
        /// ключи системных справочников
        /// </summary>
        /// <returns></returns>
        public static List<DictionaryCategoryItem> GetProviderDictionaryCategoryList() { return wsDictionary.GetProviderDictionaryCategoryList(); }
        
        /// <summary>
        /// ключи справочников агентсва
        /// </summary>
        /// <returns></returns>
        public static List<DictionaryCategoryItem> GetAgencyDictionaryCategoryList() { return wsDictionary.GetAgencyDictionaryCategoryList(); }

        

    }

    /// <summary>
    /// Проверка бизнес правил объекта
    /// </summary>
    public class BusinessRules
    {

        private static TBusinessRules _TBusinessRules = null;

        private  static TBusinessRules GetBusinessRules()
        {
            if (null == _TBusinessRules)
                _TBusinessRules = (TBusinessRules)ObjectFactory.GetNewObject("BusinessRules", "BusinessRules");

            return _TBusinessRules;
        }

        /// <summary>
        /// Проверить правила обновления
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<string> CheckUpdate(Entity obj) 
        {
            
            return GetBusinessRules().CheckUpdate(obj);            
        }
        /// <summary>
        /// ПАроверить правила удаления
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<string> CheckDelete(Entity obj)
        {
            List<string> res = new List<string>();
            return res;
        }
        /// <summary>
        /// Установка значений по умолчанию
        /// </summary>
        /// <param name="obj"></param>
        public static void SetDefaultValue(Entity obj,object [] param)
        {
             GetBusinessRules().SetDefaultValue (obj,param);            
        }

    }

    /// <summary>
    /// Навигация по страницам 
    /// </summary>
    public class PageNavigator
    { 
        /// <summary>
        /// Прямой - дословный редирект
        /// </summary>
        /// <param name="Url"></param>
        public static void Redirect (string Url)
        {
            HttpContext.Current.Response.Redirect(Url);
        }

        /// <summary>
        /// добавить параметр ReturnUrlParam
        /// </summary>
        /// <param name="Url"></param>
        public static string AddReturnUrlParam(string Url)
        {
            string s = QueryStringTools.GetReturnUrlParam();
            return String.Format(Url + "&ReturnUrlParam={0}", s);
        }


        public static string GetUrlCommand(string Url)
        {
            return Url;
        }

        /// <summary>
        /// Вернуть URL добавить объект. Пройтись по карте страниц - найти  ключ 
        /// вернуть команду - страничка?@ID=NewGuid&@ReturnUrl=страничка?параметры... 
        /// </summary>
        /// <param name="Url"></param>
        /// <returns></returns>
        public static string GetNewObjectUrlCommand(string PageKey,string ObjectTagName,Func <string,string > AddUrlHandler  )
        {
            SiteMapItem i = GetSiteMapItem(PageKey);
            if (null == i)
                throw new Exception(string.Format ("Страница по ключу {0} не найдена ", PageKey));

            string backParam=QueryStringTools.GetReturnUrlParam();            
            string s =i.GetUrl_InsertCommand(ObjectTagName, backParam);
            if (null != AddUrlHandler)
                        return AddUrlHandler(s);
            return s;
        }

        /// <summary>
        /// Вернуть URL добавить объект. Пройтись по карте страниц - найти  ключ 
        /// вернуть команду - страничка?ID=NewGuid
        /// </summary>
        /// <param name="Url"></param>
        /// <returns></returns>
        public static string GetEditObjectUrlCommand( string PageKey,string ObjectID, string ObjectTagName, Func<string, string> AddUrlHandler)
        {
            SiteMapItem i = GetSiteMapItem(PageKey);
            string backParam = QueryStringTools.GetReturnUrlParam();
            string s = i.GetUrl_EditCommand(ObjectID, ObjectTagName, backParam);
            if (null != AddUrlHandler)
                return AddUrlHandler(s);

            return (s);
            
        }



        /// <summary>
        /// Вернуть весь набор страничек доступный текущему пользователю 
        /// </summary>
        /// <returns></returns>
        public static List<SiteMapItem> GetSiteMap()
        {
            return CurrentProvider.Settings.SiteMapItems.ToList<SiteMapItem>();
        }

        public static SiteMapItem GetSiteMapItem(string PageKey)
        {
            foreach (SiteMapItem i in GetSiteMap())
            {
                if (i.PageKey.Equals(PageKey))
                    return i;
            }
            return null;
        }


    }

    /// <summary>
    /// Фабрика классов
    /// </summary>
    public class ObjectFactory
    {
        public static EntitySingle GetObject(string ID, string TagName)
        {
            return ws_SingleObectFactory.GetFactory().GetObject(ID, TagName); 
        }
                

        /// <summary>
        /// создает объект с id= CashKey; Кэш= сессия пользователя
        /// </summary>
        /// <param name="TagName"></param>
        /// <param name="CashKey"></param>
        /// <returns></returns>
        public static EntitySingle GetNewObject(string TagName,string CashKey)
        {
            EntitySingle obj = null;
            //Объект в кэше
            if (CacheTools.IsSessionCacheObject(CashKey))
            {
                obj= (EntitySingle)CacheTools.GetSessionCacheObect(CashKey);                
            }
            else            
            { 
                 obj=ws_SingleObectFactory.GetFactory().GetNewObject (TagName);
                 obj.ID = CashKey;
                 CacheTools.SetSessionCacheObject(CashKey,obj);
                 obj.ID = CashKey;
            }

            return obj;
        }

        /// <summary>
        /// Если объект новый - вычищает из ид префикс нового объекта
        /// преребрасывает объект в кэш домена - убирает объект из кэша сессии
        /// сохранение - отдельным потоком
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static EntitySingle SaveObject(EntitySingle obj)
        {
            PrepareCache(obj);
        
            /// сохраняем объект
            ws_SingleObectFactory.GetFactory().SaveObject (obj);                       
            return obj;
            
        }
        private static void PrepareCache(EntitySingle obj)
        {
            //Если запись новая - убираем префикс
            // перекидываем объект из кэша сессии в кэш домена если только это не удаление
            string ID = obj.ID;
            if (GlobalConstants.IsNewRecord(ID))
            {
                obj.ID = GlobalConstants.GetID(ID);
                //перебрасываем объект из кэша сессии в кэш домена. 
                CacheTools.ResetSessionCache(ID);
                CacheTools.SetCacheObject(obj.ID, obj);
            }

            // если удаление - чистим кэш
            if (obj.State == EntityState.Deleted)
                CacheTools.ResetCache(ID);

        }
        public static EntitySingle SaveWitchChild(EntitySingle obj)
        {
            PrepareCache(obj);
            ws_SingleObectFactory.GetFactory().SaveWitchChild(obj);
            return obj;               
        }
        



        /// <summary>
        /// синхронный save объекта.
        /// </summary>
        /// <param name="obj"></param>
        public static void  UpdateObject(EntitySingle obj)
        {
            /// сохраняем объект
            ws_SingleObectFactory.GetFactory().SaveObject(obj);                       
        }

        public static void ResetCashe(string CashKey)
        {
            CacheTools.ResetSessionCache(CashKey);
            CacheTools.ResetCache(CashKey);
            
        }
    }

    public class Securety
    {
        /// <summary>
        /// Возвращает все роли роли логина - метяться
        /// если логин пуст - просто роли 
        /// </summary>
        /// <param name="Login"></param>
        /// <returns></returns>
        public static List<ListItem> GetRoles(string Login)
        {
            List<ListItem> result = new List<ListItem>();
            
            RoleList list = new RoleList();
            list.Load();
            
            HashSet<string> hs_roles = new HashSet<string>();
            foreach (string s in GetRoles_(Login))
                                        hs_roles.Add(s);

            foreach (DictionaryItem   i in list)
            {
                ListItem item = i.ToListItem();
                item.Selected = hs_roles.Contains(i.ParamID);
                result.Add(item);
            }

            return result;
        }


        /// <summary>
        /// содать пользователя - в случае неудачи - сообщение о ошибке 
        /// </summary>
        /// <param name="Login"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string CreateUser(string Login, string Password)
        {

            try
            {

                Membership.DeleteUser(Login);
                Membership.CreateUser(Login, Password);

            }
            catch (Exception exc)
            {
                return exc.Message;
            }
            return string.Empty;
        }

        /// <summary>
        /// вернуть роли логина как массив строк
        /// </summary>
        /// <param name="Login"></param>
        /// <returns></returns>
        public static List<string> GetRoles_(string Login)
        {
            List<string> result = new List<string>();
            RoleMemberList l = new RoleMemberList() { Login = Login };
            l.Load();
            for (int i=0; i < l.Count; i++)
            { 
                result.Add ((l[i] as DictionaryItem).ParamID); 
            }
            
            return result  ;
        }
        
        /// <summary>
        /// Установить роли пользователя. Выявляет разницу между текущми ролями пользователя и заявленными
        /// Лишние удаляются - недостающие добавляются
        /// </summary>
        /// <param name="Login"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string SetUserRoles(string Login, string[] roles)
        {
            try
            {
                foreach (string role in roles)
                    Roles.AddUserToRole(Login , role);

                return string.Empty;
            }
            catch(Exception e)
            {
                return e.Message;
            }
        }


    }

    public static AgencyEntity CurrentAgency
    {
        get
        {

            return GlobalConstants.CurrentAgency; 
        }
    }

    public static Employeer CurrentEmployeer
    {
        get
        {
            return GlobalConstants.CurrentEmployeer;             
        }
    }

    public static ProviderEntity  CurrentProvider
    {
        get
        {
            return GlobalConstants.CurrentProvider;
        }
    }

    
}
